package edu.gatech.doi.spamframework.filters;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Random;

import weka.core.Attribute;
import weka.core.Instances;
import weka.core.converters.ArffSaver;
import weka.filters.Filter;
import weka.filters.unsupervised.attribute.Remove;

public class InstanceSelection {
	private String instancesdirectory=System.getProperties().getProperty("user.dir")+System.getProperties().getProperty("file.separator")+"instances"+System.getProperties().getProperty("file.separator");
/*select part of dataset according to the size*/
	public void selectPartOfData(int datasize, Instances data,String filename)
	{
		Instances ins=new Instances(data);
		ins.delete();
		for(int i=0;i<data.numInstances();i++)
		{
			if(i>datasize)
				break;
			ins.add(data.instance(i));
			
		}
		this.save2arff(ins, this.instancesdirectory, filename);
	}
	
	public void selectNMVData(Instances data,String filename)
	{
		Instances ins=new Instances(data);
		ins.delete();
		int missingnum=0;
		for(int i=0;i<data.numInstances();i++)
		{
			if(data.instance(i).value(data.numAttributes()-1)>=0.0)
			{
				ins.add(data.instance(i));
			}
			else
			{
				missingnum++;
			}
		}
		System.out.println("num of instances:"+data.numInstances());
		System.out.println("missing value num:"+missingnum);
		this.save2arff(ins, this.instancesdirectory, filename);
	}
	
	public void selectRandomNMData(Instances data,String filename,int datasize,double percentage)
	{
		Instances ins=new Instances(data);
		ins.delete();
		int totalnum=0;
		Random generator = new Random();
		int randomIndex;
		for(int i=0;i<data.numInstances();i++)
		{
			if(data.instance(i).value(data.numAttributes()-1)>=0.0)
			{
				if(i>1)
				{
					randomIndex = generator.nextInt( i );
					if(randomIndex<percentage*i)
					{
						ins.add(data.instance(i));
						totalnum++;
					}
				}
				else
				{
					ins.add(data.instance(i));
					totalnum++;
				}
				
			}
	
			if(totalnum>=datasize)
				break;
		}
		System.out.println("num of instances:"+data.numInstances());
		System.out.println("the num of total selected:"+totalnum);
		this.save2arff(ins, this.instancesdirectory, filename);
	}
	

	public void selectHamData(Instances data,String filename)
	{
		Instances ins=new Instances(data);
		ins.delete();
		int missingnum=0;
		for(int i=0;i<data.numInstances();i++)
		{
			if(data.instance(i).value(data.numAttributes()-1)==0.0)
			{
				ins.add(data.instance(i));
			}
			else
			{
				missingnum++;
			}
		}
		System.out.println("num of instances:"+data.numInstances());
		System.out.println("non-ham value num:"+missingnum);
		this.save2arff(ins, this.instancesdirectory, filename);
	}
	public void selectSpamData(Instances data,String filename)
	{
		Instances ins=new Instances(data);
		ins.delete();
		int missingnum=0;
		for(int i=0;i<data.numInstances();i++)
		{
			if(data.instance(i).value(data.numAttributes()-1)>0.0)
			{
				ins.add(data.instance(i));
			}
			else
			{
				missingnum++;
			}
		}
		System.out.println("num of instances:"+data.numInstances());
		System.out.println("non-ham value num:"+missingnum);
		this.save2arff(ins, this.instancesdirectory, filename);
	}
	
	public void setMissing(Instances data,String filename,String hamorspam)
	{
		Instances ins=new Instances(data);
		ins.delete();
		int missingnum=0;
		for(int i=0;i<data.numInstances();i++)
		{
			if(data.instance(i).value(data.numAttributes()-1)>=0.0)
			{
				ins.add(data.instance(i));
			}
			else
			{
				data.instance(i).setValue(data.numAttributes()-1, hamorspam);
				ins.add(data.instance(i));
				missingnum++;
			}
		}
		System.out.println("num of instances:"+data.numInstances());
		System.out.println("missing value num:"+missingnum);
		this.save2arff(ins, this.instancesdirectory, filename);
	}
	
	public Instances load(String dir, String filename)
	{
		BufferedReader reader;
		Instances data=null;
		try {
			reader = new BufferedReader(
			        new FileReader(dir+filename));
			data= new Instances(reader);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return data;
	}
	
	
	
	
	public void statistics(Instances data)
	{
		HashMap hm=new HashMap();
		Instances ins=new Instances(data);
		int missingnum=0;
		int spamnum=0;
		int hamnum=0;
		int j;
		for(int i=0;i<data.numInstances();i++)
		{
			
			for(j=0;j<data.instance(i).numAttributes();j++)
			{
				Attribute attr=data.instance(i).attribute(j);
				if(data.instance(i).value(attr)>=0.0)
				{
					if(hm.containsKey(attr.name()))
					{
						Integer value=(Integer)hm.get(attr.name());
						int intvalue=value.intValue();
						hm.put(attr.name(), intvalue+1);
					}
					else
					{
						Integer value=Integer.valueOf(1);
						hm.put(attr.name(), value);
					}
					
					if(attr.name().equalsIgnoreCase("LABEL"))
					{
						if(data.instance(i).value(attr)==0.0)
						{
							hamnum++;
						}
						else
							spamnum++;
					}
				}
				
			}
			
			
		}
		System.out.println("num of instances:"+data.numInstances());
		
		System.out.println("num of ham instances:"+hamnum);
		System.out.println("numof spam instances:"+spamnum);
		for( j=0;j<data.numAttributes();j++)
		{
			Attribute attr=data.attribute(j);
			System.out.println("Attribute:\t"+attr.name()+"\t the number of distinct values:\t"+data.numDistinctValues(attr));
			
		}
		//System.out.println("missing value num:"+missingnum);
		
		Iterator it=hm.keySet().iterator();
		
		while(it.hasNext())
		{
			String key=(String) it.next();
			Integer value=(Integer)hm.get(key);
			int intvalue=value.intValue();
			System.out.println("Attribute:\t"+key+"\tThe number of missing value:\t"+intvalue+"\n"
					+"Percentage of missing:\t"+((data.numInstances()-intvalue)/data.numInstances()));
			
		}
		//this.save2arff(ins, this.instancesdirectory, filename);
	}
	/**
	 * save instances to arff files
	 * @param in
	 * @param filedirectory
	 * @param filename
	 */
	public void save2arff(Instances in, String filedirectory, String filename)
	{
		 Instances dataSet =in;
		 int size=in.numInstances();
		 ArffSaver saver = new ArffSaver();
		
		 saver.setInstances(dataSet);
		 try {
//			 BufferedWriter writer = new BufferedWriter(
//                     new FileWriter(filedirectory+filename));
//			writer.write(dataSet.toString());
//			writer.newLine();
//			writer.flush();
//			writer.close();
			 saver.setFile(new File(filedirectory+filename));
			 saver.writeBatch();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 
	}
	
	public void setIntValue(Instances data,String filename)
	{
		Instances ins=new Instances(data);
		ins.delete();
		int missingnum=0;
//		data.attribute(data.numAttributes()-1).
		for(int i=0;i<data.numInstances();i++)
		{
			if(data.instance(i).value(data.numAttributes()-1)==0.0)
			{
				data.instance(i).setValue(data.numAttributes()-1, "0");
				ins.add(data.instance(i));
			}
			else if(data.instance(i).value(data.numAttributes()-1)>0.0)
			{
				data.instance(i).setValue(data.numAttributes()-1, "1");
				ins.add(data.instance(i));
				missingnum++;
			}
		}
		
		System.out.println("num of instances:"+data.numInstances());
		System.out.println("missing value num:"+missingnum);
		this.save2arff(ins, this.instancesdirectory, filename);
	}
	
	public void combineData(Instances data1, Instances data2,String filename)
	{
		
		//System.out.println("ins:"+data2);
		Instances ins=new Instances(data1);
		for(int i=0;i<data2.numInstances();i++)
		{
		
			if(data2.instance(i)!=null)
				ins.add(data2.instance(i));
			
		}
		System.out.println("ins:"+ins);
		this.save2arff(ins, this.instancesdirectory, filename);
	}
	
	public static void main(String [] args)
	{
		String instancesdirectory=System.getProperties().getProperty("user.dir")+System.getProperties().getProperty("file.separator")+"instances"+System.getProperties().getProperty("file.separator");
		InstanceSelection is=new InstanceSelection();
//		String dir=instancesdirectory;
//		String filename="trecmessage2007ham.arff";
//		Instances data=is.load(dir, filename);
//		String filename1="trecmessage2007ham3000.arff";
		
//		System.out.println("Please input the type of operation:"+
//				"1: "+
//				"2:"+
//				"3:");
		//System.in.read();
		
		int size=args.length;
		String dir = null;
		String filename = null;
		String filename1;
		String dfilename;
		int datasize;
		double percentage;
		Instances data;
		Instances data1;
		
			int type=Integer.parseInt(args[0]);
			switch(type)
			{
			case 1:
				//statistics
				dir=args[1];
				filename=args[2];
				is.instancesdirectory=dir;
				data=is.load(dir, filename);
				
				is.statistics(data);
			    break;
			case 2:
				//combine
				dir=args[1];
				filename=args[2];
				is.instancesdirectory=dir;
				data=is.load(dir, filename);
				//System.out.println("data:"+data);
				filename1=args[3];
				data1=is.load(dir, filename1);
				dfilename=args[4];
				is.combineData(data, data1, dfilename);
				break;
			case 3:
				//select random samples
				dir=args[1];
				filename=args[2];
				is.instancesdirectory=dir;
				data=is.load(dir, filename);
				dfilename=args[3];
				datasize=Integer.parseInt(args[4]);
				 percentage=Double.parseDouble(args[5]);
				is.selectRandomNMData(data, dfilename, datasize,percentage);
				break;
			case 4:
				//select ham
				dir=args[1];
				filename=args[2];
				is.instancesdirectory=dir;
				data=is.load(dir, filename);
				dfilename=args[3];
				is.selectHamData(data, dfilename);
				
				break;
			case 5:
				//select spam
				dir=args[1];
				filename=args[2];
				is.instancesdirectory=dir;
				data=is.load(dir, filename);
				dfilename=args[3];
				is.selectSpamData(data, dfilename);
				break;
			case 6:
				//select part of dataset
				dir=args[1];
				filename=args[2];
				is.instancesdirectory=dir;
				data=is.load(dir, filename);
				dfilename=args[3];
				datasize=Integer.parseInt(args[4]);
				is.selectPartOfData(datasize, data, dfilename);
				break;
			case 7:
				
				break;
			}
			
			
		}
	
		
		
		
		
		
//		is.selectNMVData(data, filename1);
//		is.selectPartOfData(3000, data, filename1);
		//is.selectRandomNMData(data, filename1,3000);
		
//		is.setMissing(data, filename1, "ham");
//		is.selectHamData(data, filename1);
//		is.setIntValue(data, filename1);
		
//		Instances data1=is.load(dir, filename1);
//		String filename2="trecmessage_2006spam4.arff";
//		is.combineData(data, data1, filename2);
		 
	
}
